<?php
/**
 * 加密/解密类
 * @authors yutent (yutent@doui.cc)
 * @date    2015-03-28 15:28:26
 *
 */

class Do_Sec {
	/**
	 * [hash 非对称加密，可选md5/sha1/混合，默认是md5方式]
	 * @param  string $str  [要加密的字符串]
	 * @param  string $mode [加密方式]
	 * @return [string]     [返回加密后的字符串，已加混淆key，长度为32/40，md5方式时是32位长度]
	 */
	function hash($str = '', $mode = 'md5', $mix = TRUE){
		global $_G;
	    $key = $mix ? $_G['key'] : '';
	    $result = '';

	    switch ($mode) {
	    	case 'sha1':
	    		$result = sha1($key . $str);
	    		break;
	    	case 'mix':
	    		$result = substr(sha1($key . $str), 0, 20).substr(md5($key . $str), 0, 20);
	    	default:
	    		$result = md5($key . $str);
	    		break;
	    }
	    return $result;
	}

	/**
	 * [base 对称加密，用于cookie等的信息加密]
	 * @param  [type] $string [要加密的字符串]
	 * @param  string $mode   [加密/解密， 默认解密]
	 * @param  string $expire [有效时长，单位秒，超过时限，即使拿到key也解密不回来]
	 * @return [type]         [返回加密后的字符串]
	 */
	function base($string, $mode = 'decode', $expire = ''){
		global $_G;

		$key = md5($_G['key']); //混淆key
		$mix_len = 32;//混淆强度，数字越大，加密后结果越长
		
		$keya = md5(substr($key, 0, 16));
		$keyb = md5(substr($key, 16, 16));
		$keyc = $mix_len ? ($mode == 'decode' ? substr($string, 0, $mix_len): substr(md5(microtime()), -$mix_len)) : '';

		$cryptkey = $keya . md5($keya . $keyc);
		$key_len = strlen($cryptkey);

		$string = $mode == 'decode' ? base64_decode(substr($string, $mix_len)) : sprintf('%010d', $expire ? $expire + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
		$string_length = strlen($string);

		$result = '';
		$box = range(0, 255);

		$rndkey = [];
		for($i = 0; $i <= 255; $i++) {
			$rndkey[$i] = ord($cryptkey[$i % $key_len]);
		}

		for($j = $i = 0; $i < 256; $i++) {
			$j = ($j + $box[$i] + $rndkey[$i]) % 256;
			$tmp = $box[$i];
			$box[$i] = $box[$j];
			$box[$j] = $tmp;
		}

		for($a = $j = $i = 0; $i < $string_length; $i++) {
			$a = ($a + 1) % 256;
			$j = ($j + $box[$a]) % 256;
			$tmp = $box[$a];
			$box[$a] = $box[$j];
			$box[$j] = $tmp;
			$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
		}

		if($mode == 'decode') {
			if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
				return substr($result, 26);
			} else {
				return '';
			}
		} else {
			return $keyc.str_replace('=', '', base64_encode($result));
		}
	}


    /**
	 * [hide 隐藏敏感字段信息]
	 * @param  string $str [要隐藏的字符串（手机号/身份证号/邮箱）]
	 * @return [type]      [返回星号替换过的字符串]
	 */
    public function hide($str = ''){
    	if(preg_match("/^\d{11}$/", $str)){
        	return preg_replace("/(\d{3})\d+(\d{4})/", '$1****$2', $str);
	    }elseif(preg_match("/^\d{17}[\d|X|x]{1}$/", $str)){
	        return substr($str, 0, 14) . '****';
	    }else{
	        return preg_replace("/([\w\.\-]{2})[\w\.\-]+@(\w{1})[\.\-\w]+(\.\w+)/", '$1***@$2**$3', $str);
	    }
    }

    /**
     * [rand 获取指定长度的随机字符]
     * @param  integer $len       [需要的随机字符串长度]
     * @param  boolean $force_num [强制返回纯数字字符串]
     * @return [type]             [description]
     */
    public function rand($len = 6, $force_num = FALSE){
		$str = '';
		$chars = 'abcdefghijkmnpqrstuvwxyz23456789';
		if($force_num === TRUE) $chars = '0123456789';

		for ( $i = 0; $i < $len; $i++ ){
			$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
		}
		return $str;
	}
}